//065959264	Limor Bagizada	040199770	Sarit Chicotay

package General;

import java.io.IOException;

import Base.Corpus;
import Base.NGram;
import Models.BaseModel;

/**
 * 
 * Perplexity is used to compare the quality of different models.
 * The model with the lowest perplexity is better (higher probability, less uncertainty) 
 *
 */
public class Perplexity {
        
		// the model that is tested 
		private BaseModel model;
		
		/**
		 * Constructor
		 * @param model - the model that is tested
		 */
        public Perplexity(BaseModel model) {
        	this.model = model;
        }
        
        /**
         * Calculate perplexity of the given model on some test corpus
         * Perplexity is calculated with this formula: 2 power (-1/n * [sum on x:](log P_d(x)))
         * (log P_d(x) in base 2)
         * @param test - test corpus
         * @return - the calculated perplexity value
         * @throws Exception 
         * @throws IOException
         */
        public double calculatePerplexity(Corpus test) throws Exception {
            double perplexity = 0;

            // summarize log base 2 of probability for all corpus words
            for (NGram event : test.getWords()) {
            	perplexity += Math.log10(model.CalculateProbability(event)) / Math.log10(2);
            }

            // Divide with minus of the test corpus size
            perplexity /= -1 * test.getSize();
            
            // calculate 2 power the previous result
            perplexity = Math.pow(2, perplexity);
            
            return perplexity;
        }
        
       
       
        
        
}